<html>
<head><meta charset="utf-8"><title>Sharing RacyCell between threads · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html">Sharing RacyCell between threads</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="233613379"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233613379" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233613379">(Apr 08 2021 at 07:33)</a>:</h4>
<p>I'm writing an emulator that stores the emulated program's memory inside some kind of <code>Box&lt;[RacyCell&lt;u8&gt;]</code> or <code>Vec&lt;RacyCell&lt;u8&gt;&gt;</code> and we had some discussion on discord whether sharing a <code>RacyCell</code> between threads is safe</p>
<p>This emulator doesn't really care about what data it will get from the "race", it only gives the emulated process what it is asking for</p>
<p>My thinking is, wrapping bytes in <code>UnsafeCell</code> would make compiler assume the data is shared and that it can be mutated any time making this abstraction "sound enough"</p>



<a name="233613902"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233613902" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233613902">(Apr 08 2021 at 07:38)</a>:</h4>
<p>This reminds me of <span class="user-mention" data-user-id="209168">@Thom Chiovoloni</span> 's <a href="https://shift.click/blog/tearcell/"><code>TearCell</code></a></p>



<a name="233613936"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233613936" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233613936">(Apr 08 2021 at 07:38)</a>:</h4>
<p>The main argument is that "races are UB no matter what"<br>
Well, they are UB, because language can't specify what will be the exact result of a race, but the emulator doesn't really care about it</p>



<a name="233613986"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233613986" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233613986">(Apr 08 2021 at 07:39)</a>:</h4>
<p>The UB is on the emulated program side</p>



<a name="233614163"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233614163" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233614163">(Apr 08 2021 at 07:40)</a>:</h4>
<p>I think it's okay to have a program which pushes some UB to runtime, in the sense that there are certain inputs that cause UB but the program itself comes with a safety condition on users to not exercise those code paths</p>



<a name="233614308"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233614308" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233614308">(Apr 08 2021 at 07:42)</a>:</h4>
<p>However, that means that you have to be okay with an emulator that makes no guarantees about what the emulator does in the face of a bad input program, which is an unusual choice for an interpreter</p>



<a name="233614807"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233614807" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> FishTrashPlaneCurtain <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233614807">(Apr 08 2021 at 07:47)</a>:</h4>
<p>Hello, I was the person on the other side of the discord discussion. I'm not too convinced it's ok to say "this is UB iff the input program causes UB". It's still UB. The compiler is free to optimize assuming it _never_ happens.</p>
<p>"They are UB, because language can't specify what will be the exact result of a race" is not the whole story.</p>
<p>The language is allowed to completely change the code around in ways that cause SIGSEGV on a data race. Or even cause the instruction pointer to jump inside the emulated program, allowing it to execute arbitrary code as if it were the emulator.</p>
<p>Making a racy read and getting garbage is literally the best thing that can happen. It is by no means the worst.</p>



<a name="233615230"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615230" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615230">(Apr 08 2021 at 07:51)</a>:</h4>
<blockquote>
<p>The compiler is free to optimize assuming it _never_ happens.</p>
</blockquote>
<p>Well, yes. That's what I mean by pushing UB to run time: the author of the rust emulator is disclaiming all responsibility for what happens if code triggers the UB path, and uses this to be able to make a promise to the compiler that UB doesn't happen. The onus now falls on the author of the emulated code to ensure that they don't write a program containing emulated UB. As long as they do this, the emulator's promise is satisfied and so is the compiler's.</p>



<a name="233615254"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615254" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615254">(Apr 08 2021 at 07:51)</a>:</h4>
<blockquote>
<p>The compiler is free to optimize assuming it _never_ happens</p>
</blockquote>
<p>That is exactly what I'm expecting - a casual read/write - nothing less, nothing more</p>



<a name="233615436"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615436" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615436">(Apr 08 2021 at 07:52)</a>:</h4>
<p>The <code>TearCell</code> approach is a bit different; it makes all races non-UB by resulting in data corruption instead, which is probably a fine alternative for emulated UB, if you don't want to actually produce a "partial program"</p>



<a name="233615647"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615647" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615647">(Apr 08 2021 at 07:54)</a>:</h4>
<blockquote>
<p>That is exactly what I'm expecting - a casual read/write - nothing less, nothing more</p>
</blockquote>
<p>And I have to do it, because unaligned atomics are even more UB</p>



<a name="233615685"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615685" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615685">(Apr 08 2021 at 07:55)</a>:</h4>
<p>unaligned atomic operations are pretty easy to trap though</p>



<a name="233615732"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615732" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615732">(Apr 08 2021 at 07:55)</a>:</h4>
<p>but what is suggested is every casual operation gets promoted to atomic operation in emulation</p>



<a name="233615800"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615800" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> FishTrashPlaneCurtain <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615800">(Apr 08 2021 at 07:56)</a>:</h4>
<p>I guess if your semantics are "emulated programs that cause a data race are UB" it _may_ be fine?</p>
<p>You have to be  _very careful_, tho. You could end up with a program that has a vulnerability. If you need to be secure _at all_ this won't do</p>



<a name="233615802"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615802" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615802">(Apr 08 2021 at 07:56)</a>:</h4>
<p>and it is common to have unaligned reads/writes supported on cpus</p>



<a name="233615929"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615929" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615929">(Apr 08 2021 at 07:58)</a>:</h4>
<p>If you are talking about the TearCell implementation, I think it automatically splits reads into appropriately aligned (<code>Unordered</code>) atomic operations</p>



<a name="233615992"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233615992" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233615992">(Apr 08 2021 at 07:59)</a>:</h4>
<p>I'm pretty sure that aligned unordered atomic operations compile to plain reads and writes on basically every arch</p>



<a name="233616260"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233616260" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233616260">(Apr 08 2021 at 08:01)</a>:</h4>
<p>This isn't only about store/write, it is also about and/or/xor/add/sub/mul/div</p>



<a name="233616293"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233616293" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233616293">(Apr 08 2021 at 08:01)</a>:</h4>
<p>you don't even have atomic ops for some of them</p>



<a name="233617340"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233617340" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233617340">(Apr 08 2021 at 08:12)</a>:</h4>
<p>I would expect that if you just (atomic) read, perform your operation, and then (atomic) write, and set the atomics to the lowest setting, you will get the same codegen as normal</p>



<a name="233617545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233617545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233617545">(Apr 08 2021 at 08:15)</a>:</h4>
<p>The main thing you will be missing is the ability to perform read/write compiler optimizations, and that's not usually an issue for interpreters since there isn't much to optimize, but if it's a JIT compiler then that might be a performance issue</p>



<a name="233618381"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233618381" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233618381">(Apr 08 2021 at 08:24)</a>:</h4>
<p>Yeah, for now as it is an interpreter, it could use something like TearCell, since MMU stuff will consume most of cpu time</p>



<a name="233618693"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233618693" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233618693">(Apr 08 2021 at 08:28)</a>:</h4>
<p>but later i probably would want to have some sort of 1:1 mapping between emulated -&gt; emulator memory space</p>



<a name="233618939"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233618939" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233618939">(Apr 08 2021 at 08:30)</a>:</h4>
<p>and it can make a difference</p>



<a name="233619753"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233619753" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233619753">(Apr 08 2021 at 08:38)</a>:</h4>
<p>maybe similar to <code>MaybeUninit::assume_init</code> we should also have <code>RacyCell::assume_nonracy_read/write</code> <span aria-label="thinking" class="emoji emoji-1f914" role="img" title="thinking">:thinking:</span></p>



<a name="233620596"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233620596" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> hyd-dev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233620596">(Apr 08 2021 at 08:46)</a>:</h4>
<p><a href="https://github.com/rust-lang/rust/issues/19835">#19835</a> looks interesting:</p>
<blockquote>
<p>Valid uses of this ordering are things like racy counters where you don't care about the operation actually being atomic, just want to avoid UB.</p>
</blockquote>



<a name="233633829"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233633829" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233633829">(Apr 08 2021 at 10:55)</a>:</h4>
<p>Oh hey, someone mentioned my blog <span aria-label="heart" class="emoji emoji-2764" role="img" title="heart">:heart:</span>. The main use case for TearCell is as a building block for stuff like seqlocks (and other optimistic concurrency primitives), but yeah it's definitely usable for any case where what you want is a datarace-but-no-ub-please. (I meant to follow up with a post on these use cases, but, well, I have a lot of posts I'd like to write)</p>
<p>Anyway, tearcell has a couple minor issues in the implementation that I havent gotten around to fix:</p>
<ul>
<li>if you have a large struct with a small alignment it won't use a very good algo for copying stuff (it will do it per-byte — wheras if it's higher alignment it does it with the largest atomic type available).</li>
<li>Also it uses AtomicU64 for stuff with align_of &gt;= 8 on all arches, but it shouldn't on arm32, where AtomicU64 is supported but slower than AtomicUsize.</li>
</ul>
<p>(I also still wish that it were definable without requiring bytemuck::Pod bound, but I'm pretty sure that it turned out that my paranoia there was warranted and using it with types that e.g. have padding would be no bueno)</p>



<a name="233633963"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233633963" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233633963">(Apr 08 2021 at 10:57)</a>:</h4>
<p><span class="user-mention silent" data-user-id="374396">hyd-dev</span> <a href="#narrow/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads/near/233620596">said</a>:</p>
<blockquote>
<p><a href="https://github.com/rust-lang/rust/issues/19835">#19835</a> looks interesting:</p>
<blockquote>
<p>Valid uses of this ordering are things like racy counters where you don't care about the operation actually being atomic, just want to avoid UB.</p>
</blockquote>
</blockquote>
<p>Unordered is basically Relaxed in this context</p>



<a name="233634072"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233634072" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233634072">(Apr 08 2021 at 10:58)</a>:</h4>
<p>it is still atomic, but can be reordered with other atomics, unlike Relaxed</p>



<a name="233634163"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233634163" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233634163">(Apr 08 2021 at 10:59)</a>:</h4>
<p>For a case like <code>Box&lt;[RacyCell&lt;u8&gt;]&gt;</code> I'd just do <code>Box&lt;[AtomicU8]&gt;</code> and use relaxed atomics. TearCell is not really useful for a type which has a direct atomic equivalent, since it's just doing relaxed ops.</p>
<p>You could also use stuff like</p>
<ul>
<li><a href="https://doc.rust-lang.org/core/intrinsics/fn.atomic_load_unordered.html">https://doc.rust-lang.org/core/intrinsics/fn.atomic_load_unordered.html</a></li>
<li><a href="https://doc.rust-lang.org/core/intrinsics/fn.atomic_store_unordered.html">https://doc.rust-lang.org/core/intrinsics/fn.atomic_store_unordered.html</a></li>
</ul>
<p>LLVM is willing to optimize these much more aggressively than relaxed, but you won't see it for all cases. Its really hard to find a way to use them in real concurrent code too — I've managed to write a couple algorithms that are coherent under the minimal guarantee they provide in multithreaded usage (which are something like "a value loaded with an unordered load was definitely stored at one point"), but most traditional ones require at least monotonic progress, as provided by relaxed</p>



<a name="233634570"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233634570" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233634570">(Apr 08 2021 at 11:03)</a>:</h4>
<p>i really think about manually loading the memory via</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="fm">asm!</span><span class="p">(</span><span class="s">"mov {}, [{}]"</span><span class="p">,</span><span class="w"> </span><span class="n">lateout</span><span class="p">(</span><span class="n">reg</span><span class="p">)</span><span class="w"> </span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="k">in</span><span class="p">(</span><span class="n">reg</span><span class="p">)</span><span class="w"> </span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="n">options</span><span class="p">(</span><span class="n">nostack</span><span class="p">))</span><span class="w"></span>
</code></pre></div>



<a name="233634825"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233634825" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233634825">(Apr 08 2021 at 11:06)</a>:</h4>
<blockquote>
<p>it is still atomic, but can be reordered with other atomics, unlike Relaxed</p>
</blockquote>
<p>The big differnce is that relaxed accesses to the same atomic can't be reordered across eachother, and that it's very hard for LLVM to do much clever like combine, elide, or otherwise optimize the accesses. In practice it has very different guarantees from it, but often behaves a bit like a volatile op — for the time being, it's almost certainly going to go to memory, and happen where you wrote it. (That said, there's the promise in the future that some of this may be improved... hopefully)</p>
<p>That said it's not like unordered is much better. I've seen LLVM do wonders with it, and I've also seen LLVM completely fail to optimize it any any better than relaxed. It was really finnickey, and not always that much of a win.</p>
<p>And really, relaxed is fine most of the time since what you're more concerned about is fencing.</p>



<a name="233635403"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233635403" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233635403">(Apr 08 2021 at 11:12)</a>:</h4>
<p>there wouldn't be much to optimize, load/store is basically one operation and the rest is MMU stuff</p>



<a name="233635500"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233635500" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233635500">(Apr 08 2021 at 11:13)</a>:</h4>
<p>My understanding about the asm case is that it's still UB to do that if you immediately extract the value.</p>
<p>IIUC, it's only not UB to cheat the rules in an asm block if the cheating happens fully in the asm block — if you extract a value that would be <code>undef</code> or <code>poison</code>, it's still UB to return it to rust. If you do everything you need to do with it entirely within the ASM block and produce a fully well-defined result. </p>
<p>For example, in a string match function, you might have an asm block that read past the end of an array (assuming you handle page boundaries properly etc), determines the result of the match within the asm, and returns the result of that to rust, but you can't have one that just reads past the end and passes it to rust.</p>
<p>That is, i believe the asm block there is semantically equivalent to a volatile read, which isn't enough to escape UB. (In theory anway, in practice it likely is)</p>



<a name="233635850"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233635850" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233635850">(Apr 08 2021 at 11:17)</a>:</h4>
<p>to be precise, not only volatile, also unaligned</p>



<a name="233636035"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233636035" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233636035">(Apr 08 2021 at 11:20)</a>:</h4>
<p>Unordered like any other atomic can't have loads/stores merged together</p>



<a name="233637191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233637191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233637191">(Apr 08 2021 at 11:32)</a>:</h4>
<p>or are data races UB because some really old hardware used to catch fire?<br>
if one core tried to zero (ground) a memory cell and the other one set it, the circuit would close</p>



<a name="233637596"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233637596" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233637596">(Apr 08 2021 at 11:36)</a>:</h4>
<p><span class="user-mention silent" data-user-id="328907">Soveu</span> <a href="#narrow/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads/near/233636035">said</a>:</p>
<blockquote>
<p>Unordered like any other atomic can't have loads/stores merged together</p>
</blockquote>
<p>I think it can have them merged, no? obviously not split. Merging would introduce mixed size access, but given the semantics of unordered I don't see how that would be a problem on most hardware</p>



<a name="233638011"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233638011" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233638011">(Apr 08 2021 at 11:40)</a>:</h4>
<p><a href="https://releases.llvm.org/8.0.0/docs/Atomics.html#unordered">https://releases.llvm.org/8.0.0/docs/Atomics.html#unordered</a></p>
<div class="codehilite"><pre><span></span><code>In terms of the optimizer, this prohibits any transformation that transforms a single load into
multiple loads,transforms a store into multiple stores, narrows a store, or stores a value which
would not be stored otherwise.
Some examples of unsafe optimizations are narrowing an assignment into a bitfield,
rematerializing a load, and turning loads and stores into a memcpy call. Reordering
unordered operations is safe, though, and optimizers should take advantage of that
because unordered operations are common in languages that need them.
</code></pre></div>



<a name="233683252"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233683252" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233683252">(Apr 08 2021 at 16:21)</a>:</h4>
<p>that seems more restrictive than what java's default, non-atomic access promises</p>



<a name="233684091"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233684091" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233684091">(Apr 08 2021 at 16:27)</a>:</h4>
<p>Ah, it relies on the frontend to do the narrowing. Still, I'm not sure if the restriction on rematerialization is necessary.</p>



<a name="233907567"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233907567" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233907567">(Apr 09 2021 at 23:47)</a>:</h4>
<p>Hm? The LLVM docs don't say that it can't transform multiple loads into a single load, or multiple stores into single stores, which is what I meant by merging. It explicitly forbids the opposite of that, however.</p>



<a name="233940352"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/233940352" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#233940352">(Apr 10 2021 at 09:07)</a>:</h4>
<p>for now relaxed load of <code>[AtomicU8; 4]</code> are basically 4 different loads, idk how it will look with Unordered</p>



<a name="234019809"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/234019809" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#234019809">(Apr 11 2021 at 06:14)</a>:</h4>
<p>It's definitely allowed to merge those for unordered. I don't think so for Relaxed — mixed sized accesses are very weird and not particularly well specified.</p>
<p>In practice with mixed size accesses, even if you used seqcst for all of them, i believe you don't actually get sequential consistency on a lot of hardware (exception being on x86) — there's just no way to have that fence. so, this is likely part of why compilers may avoid it if they do.</p>
<p>Doesn't really apply to Unordered though.</p>



<a name="234028485"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Sharing%20RacyCell%20between%20threads/near/234028485" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Soveu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Sharing.20RacyCell.20between.20threads.html#234028485">(Apr 11 2021 at 08:49)</a>:</h4>
<p>with Unordered it's so weird<br>
load is split, store is also split<br>
<a href="https://godbolt.org/z/TMKqrK8hj">https://godbolt.org/z/TMKqrK8hj</a><br>
fun fact: when store or load is inside a for loop, it calls <code>llvm_memcpy_unordered</code> or something like that</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>